<?php

/**
 * Presenter pro spravu sablon hromadne aktualizace.
 *
 * @author David Dusek
 */

class TemplatePresenter extends \AdminPresenter
{
    public function renderDefault() {
        $this->template->title = $this->getTitle("templateTitle", "list");
//        $client = new \Updater\JsonRpc\JsonRpcClient("http://fit-cms.local/admin/updater/remote/");
//        // Vrácení seznamu metod a zaregistrování panelu se seznamem metod
//        Nette\Diagnostics\Debugger::dump($client->getListOfMethod());
//
//        // Volání vzdálených metod
//        Nette\Diagnostics\Debugger::dump($client->update());
    }
    
    public function renderAdd() {
        $this->template->title = $this->getTitle("templateTitle", "add");
    }
    
    public function renderEdit($id) {
        $this->template->title = $this->getTitle("templateTitle", "edit");
        
        $id = $this->getParameter("id");
        $repository = $this->em->getRepository("CMS\Updater\Models\Template");        
        if ($id === NULL || ($template = $repository->find($id)) === NULL) {     
            $this->flashMessage($this->translate("errTemplateIdNotFound"), "error");
            $this->redirect(":Updater:Template:default");
        }
        $this->template->templateEntity = $template;
    }
    
    public function renderUpdate($id) {
        $this->template->title = $this->getTitle("templateTitle", "update");
        
        $id = $this->getParameter("id");
        $repository = $this->em->getRepository("CMS\Updater\Models\Template");        
        if ($id === NULL || ($template = $repository->find($id)) === NULL) {     
            $this->flashMessage($this->translate("errTemplateIdNotFound"), "error");
            $this->redirect(":Updater:Template:default");
        }
        $this->template->templateEntity = $template;
        
        // nalezení poslední aktualizace
        $updateRep = $this->em->getRepository("CMS\Updater\Models\Update");
        $this->template->lastUpdate = $updateRep->getLast();
    }
    
    protected function createComponentGrid() {
        $grid = new Gridito\Grid($this, 'grid');
       
        $qb = $this->em->getRepository('\CMS\Updater\Models\Template')->createQueryBuilder('t');
        $grid->setModel(new CMS\DoctrineQueryBuilderModel($qb));
        $grid->addColumn('id', 'Id')->setSortable(true);
        $grid->addColumn('name', $this->translate('name'))->setSortable(true);
        $grid->addColumn('svnPath', $this->translate('svnPath'));
        $grid->addColumn('domainsCount', $this->translate('domainsCount'));
             
        $presenter = $this;
        if ($this->isAllowed("edit")) {
            $grid->addButton('editButton', $this->translate('edit'), array(
                            'icon' => 'ui-icon-pencil',
                            'handler' => function ($template) use ($presenter) {
                                $presenter->redirect(':Updater:Template:edit', array("id" => $template->id));
                            },
                    ))
                    ->setShowText(false);
            $grid->addButton('updateButton', $this->translate('update'), array(
                            'icon' => 'ui-icon-refresh',
                            'handler' => function ($template) use ($presenter) {
                                $presenter->redirect(':Updater:Template:update', array("id" => $template->id));
                            },
                    ))
                    ->setShowText(false);
        }
        
        $em = $this->em;
        $msgErr = $presenter->translate("errTemplateNotEmpty");
        $msgSucc = $presenter->translate("msgTemplateDeleted");
        if ($this->isAllowed("delete")) {
            $grid->addButton('deleteButton', $this->translate('delete'), array(
                            'icon' => 'ui-icon-trash',
                            'handler' => function ($template) use ($grid, $presenter, $msgErr, $msgSucc, $em) {
                                if ($template->domainsCount > 0) {
                                    $grid->flashMessage(vsprintf($msgErr, array($template->name)));
                                } else {
                                    $em->remove($template);
                                    $em->flush();
                                    $grid->flashMessage(vsprintf($msgSucc, array($template->name)));
                                }
                            },
                    ))
                    ->setConfirmationQuestion($this->translate('deleteTemplateConfirmQuestion'))
                    ->setShowText(false)
                    ->setAjax(true);
        }
    }
    
    protected function createComponentTemplateForm() {
        $form = new Nette\Application\UI\Form;
        
        $repository = $this->em->getRepository("\CMS\Updater\Models\Template");
        
        $form->addText("name", $this->translate("name"))->setRequired($this->translate("errRequired"));
        $form->addText("svnpath", $this->translate("svnPath"))->setRequired($this->translate("errRequired"));
        $form->addText("svndir", $this->translate("svnDir"))->setRequired($this->translate("errRequired"));
        $form->addText("svnname", $this->translate("svnName"));
        $form->addPassword("svnpass", $this->translate("svnPass"));        
        
        if ($this->action == "add") {
            $form->addSubmit("add", $this->translate("add"));
        } else {
            $id = $this->getParameter("id");
            if ($id !== NULL && ($template = $repository->find($id)) !== NULL) {                
                $form->addMultiSelect("modules", $this->translate("modules"), $this->getAllMossibleModules($template->domains), 10);
                
                $values = array();
                $values["name"] = $template->name;
                $values["svnpath"] = $template->svnPath;
                $values["svndir"] = $template->svnDir;
                $values["svnname"] = $template->svnName;
                $values["svnpass"] = $template->svnPass;
                $values["modules"] = $template->modules;
                $form->setDefaults($values);
            }
            $form->addSubmit("edit", $this->translate("edit"));
        }

        $form->onSuccess[] = callback($this, 'templateFormSubmitted');
        return $form;
    }
    
    public function templateFormSubmitted(Nette\Application\UI\Form $form) {
        $values = $form->getValues();
        $action = $this->action;
        $repository = $this->em->getRepository("CMS\Updater\Models\Template");
        
        if ($action == "add") {
            $template = new CMS\Updater\Models\Template;
            $this->flashMessage($this->translate("msgTemplateAdded"));
        } else {
            $id = $this->getParameter("id");
            if ($id === NULL || ($template = $repository->find($id)) === NULL) {
                $this->flashMessage($this->translate("errTemplateIdNotFound"), "error");
                $this->redirect(":Updater:Template");
            }
            
            $template->modules = $values["modules"];
            $this->flashMessage($this->translate("msgTemplateEdited"));
        }
        
        $template->name = $values["name"];
        $template->svnPath = $values["svnpath"];
        $template->svnDir = $values["svndir"];
        $template->svnName = $values["svnname"];
        $template->svnPass = $values["svnpass"];        
        
        $this->em->persist($template);
        $this->em->flush();
        
        $this->redirect(":Updater:Template:edit", array("id" => $template->id));
    }
    
    /**
     * Metoda ziska seznam vsech modulu z domen predanych jako parametr.
     * @param array $domains Seznam entit domen.
     * @return array Seznam modulu. 
     */
    private function getAllMossibleModules($domains) {
        $modules = array();
        
        foreach ($domains as $domain) {
            try {                
                $client = new \Updater\JsonRpc\JsonRpcClient($domain->url);
                $encoded = UpdaterModule::encode(array($domain->sharedKey), $domain->sharedKey);
                
                $modules = array_merge($modules, $client->getModules($encoded));
            } catch (JsonRpc\JsonRpcException $e){
//                $form->addError(vsprintf($this->translate("rpcServerError"), array($e->getMessage())));
            } catch (Updater\JsonRpc\JsonRpcException $e){
//                $form->addError(vsprintf($this->translate("rpcServerError"), array($e->getMessage())));
            }
        }
        
        return array_unique($modules);
    }
    
    public function handleUpdateDomain($id, $templateId) {
        $domainRep = $this->em->getRepository("CMS\Updater\Models\Domain");
        $templateRep = $this->em->getRepository("CMS\Updater\Models\Template");
        
        $domain = $domainRep->find($id);
        $template = $templateRep->find($templateId);
        
        if ($domain === NULL || $template === NULL) {
            $this->payload->updateStatus = FALSE;
            $this->payload->updateMsg = "updater_domainORTemplateNotExists";
        }
                        
        $params = array(            
            $template->svnPath,
            $template->svnDir,
            $template->svnName,
            $template->svnPass,
            implode(';', $template->modules),
            $domain->sharedKey,
        );
        
        try {                
            $client = new \Updater\JsonRpc\JsonRpcClient($domain->url);
            $encoded = UpdaterModule::encode($params, $domain->sharedKey);
            $result = $client->update($encoded);            
            
            // domena neexistuje
            if ($result === null) {
                $this->payload->updateStatus = FALSE;
                $this->payload->updateMsg = $this->translate("remoteConnectionFail");
            } else if ($result["status"]) { // povedlo se
                $this->payload->updateStatus = TRUE;
            } else { //aktualizace selhala a problem pod klicem msg
                $this->payload->updateStatus = FALSE;
                $this->payload->updateMsg = $this->translate($result["msg"]);
            }
            
        } catch (JsonRpc\JsonRpcException $e){
            $this->payload->updateStatus = FALSE;
            $this->payload->updateMsg = vsprintf($this->translate("rpcServerError"), array($e->getMessage()));
        } catch (Updater\JsonRpc\JsonRpcException $e){
            $this->payload->updateStatus = FALSE;
            $this->payload->updateMsg = vsprintf($this->translate("rpcServerError"), array($e->getMessage()));
        } catch (\Exception $e) { 
            $this->payload->updateStatus = FALSE;
            $this->payload->updateMsg = $this->translate("unknownRemoteErr");
            
            $client = new \Updater\JsonRpc\JsonRpcClient($domain->url);
            $encoded = UpdaterModule::encode($params, $domain->sharedKey);
            $result = $client->rollback($encoded);
        }
        
        $this->sendPayload();
    }
    
    public function handleUpdateFinish($templateId) {
        $templateRep = $this->em->getRepository("CMS\Updater\Models\Template");
        $template = $templateRep->find($templateId);
        
        $log = new \CMS\Updater\Models\Update();
        $log->modules = $template->modules;
        $log->svnPath = $template->svnPath;
        $log->svnDir = $template->svnDir;
        foreach ($template->domains as $domain) {
            $log->addDomain($domain);
        }
        $this->em->persist($log);
        $this->em->flush();
    }
    
    public function revertDomain($domainId, $updateId) {
        $updateRep = $this->em->getRepository("CMS\Updater\Models\Update");
        $domainRep = $this->em->getRepository("CMS\Updater\Models\Domain");
        
        $update = $updateRep->find($updateId);
        $domain = $domainRep->find($domainId);
        
        if ($domain === NULL || $update === NULL) {
            $this->payload->revertStatus = FALSE;
            $this->payload->revertMsg = "updater_domainORUpdateNotExists";
        }
        
        try {                
            $client = new \Updater\JsonRpc\JsonRpcClient($domain->url);
            $encoded = UpdaterModule::encode(array($domain->sharedKey), $domain->sharedKey);

            $result = $client->revert($encoded);
            // povedlo se
            if ($result["status"]) {
                $this->payload->revertStatus = TRUE;
            } else { //aktualizace selhala a problem pod klicem msg
                $this->payload->revertStatus = FALSE;
                $this->payload->revertMsg = $this->translate($result["msq"]);
            }
            
        } catch (JsonRpc\JsonRpcException $e){
            $this->payload->revertStatus = FALSE;
            $this->payload->revertMsg = vsprintf($this->translate("rpcServerError"), array($e->getMessage()));
        } catch (Updater\JsonRpc\JsonRpcException $e){
            $this->payload->revertStatus = FALSE;
            $this->payload->revertMsg = vsprintf($this->translate("rpcServerError"), array($e->getMessage()));
        }
        
        $this->sendPayload();
    }
    
    public function handleRevertFinish($updateId) {
        $updateRep = $this->em->getRepository("CMS\Updater\Models\Update");
        $update = $updateRep->find($updateId);
        
        $this->em->remove($update);
        $this->em->flush();
    }
}
